package com.jiayou.client

import android.app.Activity
import android.content.Context
import android.media.MediaPlayer
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.recyclerview.widget.RecyclerView
import com.jiayou.R
import com.jiayou.activity.MainActivity
import com.jiayou.activity.adapter.ChatMessage
import com.jiayou.activity.adapter.MessageAdapter
import com.jiayou.codec.ChannelDecoder
import com.jiayou.codec.ChannelEncoder
import com.jiayou.message.ChannelMessage
import com.jiayou.message.HeartbeatMessage
import com.jiayou.message.OnLineMessage
import com.jiayou.message.TextMessage
import com.jiayou.message.type.DataType
import com.jiayou.message.type.NetWorkType
import com.jiayou.tool.SerializableTool
import io.netty.bootstrap.Bootstrap
import io.netty.channel.*
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioSocketChannel
import io.netty.handler.timeout.IdleState
import io.netty.handler.timeout.IdleStateEvent
import io.netty.handler.timeout.IdleStateHandler
import kotlinx.android.synthetic.main.activity_chat.*
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread

class ImClient(var context: Context, var username: String, var host: String, var port: Int) {
    lateinit var server: ChannelFuture
    var player: MediaPlayer = MediaPlayer.create(context, R.raw.coin01)

    ////////////////////////////////////
    ////////////////////////////////////
    var list: ArrayList<ChatMessage>? = null
    var recyclerview: RecyclerView? = null
    var adapter: RecyclerView.Adapter<MessageAdapter.MessageViewHolder>? = null
    var who: String? = null
    ////////////////////////////////////
    ////////////////////////////////////

    fun startClient() {

        while (true) {
            val boss = NioEventLoopGroup()
            val bootstrap = Bootstrap()
            bootstrap.group(boss)
                .channel(NioSocketChannel::class.java)
                .handler(object : ChannelInitializer<SocketChannel>() {
                    override fun initChannel(p0: SocketChannel) {
                        p0.pipeline().addFirst(ChannelEncoder())
                        p0.pipeline().addFirst(ChannelDecoder())
                        p0.pipeline().addLast(IdleStateHandler(5, 5, 1000, TimeUnit.SECONDS))
                        p0.pipeline().addLast(object : ChannelInboundHandlerAdapter() {
                            @RequiresApi(Build.VERSION_CODES.M)
                            override fun userEventTriggered(
                                ctx: ChannelHandlerContext?,
                                evt: Any?
                            ) {
                                if (evt is IdleStateEvent) {
                                    when (evt.state()) {
                                        IdleState.READER_IDLE -> {
                                            println("读空闲，我得给服务器发送个心跳包试试")
                                            val array = SerializableTool.ObjectToByteArray(
                                                HeartbeatMessage(
                                                    ctx?.channel()?.localAddress().toString(),
                                                    getNetWorkType(context)
                                                )
                                            )
                                            ctx?.writeAndFlush(
                                                ChannelMessage(
                                                    array.size,
                                                    DataType.HEARTBEAT,
                                                    array
                                                )
                                            )
                                        }
                                        IdleState.WRITER_IDLE -> println(
                                            "${ctx?.channel()?.remoteAddress()}写空闲"
                                        )
                                        IdleState.ALL_IDLE -> println(
                                            "${ctx?.channel()?.remoteAddress()}读写空闲"
                                        )
                                        else -> println(
                                            "${ctx?.channel()?.remoteAddress()}事件可能为NULL"
                                        )
                                    }
                                }

                            }
                        })
                        p0.pipeline()
                            .addLast(object : SimpleChannelInboundHandler<ChannelMessage>() {

                                override fun channelRead0(
                                    ctx: ChannelHandlerContext?,
                                    msg: ChannelMessage?
                                ) {
                                    val obj = SerializableTool.ByteArrayToObject(msg?.byteArray)
                                    when (msg?.dataType) {
                                        DataType.BINARY -> {
                                            println("BINARY")
                                        }
                                        DataType.OFFLINE -> {
                                            println("OFFLINE")
                                        }
                                        DataType.ONLINE -> {
                                            println("ONLINE")
                                        }
                                        DataType.TEXT -> {
                                            val textMessage = obj as TextMessage //在信道发送消息

                                            if (!player.isPlaying)
                                                player.start()

                                            if (list != null && who != null && recyclerview != null && adapter != null && who == textMessage.from) {
                                                list?.add(
                                                    ChatMessage(
                                                        id1 = textMessage.from,
                                                        id2 = textMessage.to,
                                                        text = textMessage.text
                                                    )
                                                )
                                                (context as MainActivity).runOnUiThread {
                                                    list?.size?.minus(1)?.let {
                                                        adapter?.notifyItemInserted(
                                                            it
                                                        )
                                                    }
                                                    list?.size?.minus(
                                                        1
                                                    )?.let {
                                                        recyclerview?.scrollToPosition(
                                                            it
                                                        )
                                                    }
                                                }
                                            }

//                                            (context as MainActivity).runOnUiThread {
//                                                Toast.makeText(
//                                                    context,
//                                                    textMessage.text,
//                                                    Toast.LENGTH_SHORT
//                                                ).show()
//                                            }
                                            println("TEXT")
                                            println(textMessage)
                                        }
                                        DataType.HEARTBEAT -> {
                                            println("受到服务的心跳")
                                        }
                                    }
                                }

                                override fun channelActive(ctx: ChannelHandlerContext?) {
                                    val array =
                                        SerializableTool.ObjectToByteArray(
                                            OnLineMessage(
                                                username,
                                                "继续努力"
                                            )
                                        )
                                    val length = array.size
                                    ctx?.writeAndFlush(
                                        ChannelMessage(
                                            length,
                                            DataType.ONLINE,
                                            array
                                        )
                                    )
                                }
                            })
                    }
                })

            server = bootstrap.connect(host, port).sync()
            server.addListener {
                if (it.isSuccess)
                    (context as Activity).runOnUiThread {
                        Toast.makeText(context, "连接服务器成功", Toast.LENGTH_SHORT).show()
                        thread {
                            while (true) {
                                if (!server.channel().isOpen) {

                                }
                            }
                        }
                    }
                else
                    (context as Activity).runOnUiThread {
                        Toast.makeText(context, "连接服务器失败", Toast.LENGTH_SHORT).show()
                    }
            }
            server.channel().closeFuture().sync()
            boss.shutdownGracefully()
            (context as Activity).runOnUiThread {
                Toast.makeText(context, "服务器断开了", Toast.LENGTH_SHORT).show()
                Toast.makeText(context, "尝试和服务器重新建立连接", Toast.LENGTH_SHORT).show()
            }

        }
    }

    //返回网络状体
    @RequiresApi(Build.VERSION_CODES.M)
    fun getNetWorkType(context: Context): NetWorkType {

        val type: NetWorkType
        val connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

        type = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)?.let {
            when {
                it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> return@let NetWorkType.WIFI
                it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> return@let NetWorkType.GPRS
                else -> return@let NetWorkType.NULL
            }
        }!!
        return type
    }
}